package com.lz.nacos.common.redis;

import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * spring nacos 工具类
 *
 * @author xpp
 **/
@SuppressWarnings(value = {"unchecked", "rawtypes"})
@Component
public class RedisSortSetCache {
    @Resource
    public RedisTemplate redisTemplate;

    /**
     * 设置有效时间
     *
     * @param key     Redis键
     * @param timeout 超时时间
     * @return true=设置成功；false=设置失败
     */
    public boolean expire(final String key, final long timeout) {
        return expire(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 设置有效时间
     *
     * @param key     Redis键
     * @param timeout 超时时间
     * @param unit    时间单位
     * @return true=设置成功；false=设置失败
     */
    public boolean expire(final String key, final long timeout, final TimeUnit unit) {
        return redisTemplate.expire(key, timeout, unit);
    }


    /**
     * set中增加元素，支持一次增加多个元素，逗号分隔即可，结果返回添加的个数
     *
     * @param key
     * @param value
     * @return
     */
    public Boolean addSet(String key, Object value, double score) {
        Boolean b = null;
        try {
            b = redisTemplate.opsForZSet().add(key, value, score);
        } catch (Exception e) {
            return b;
        }
        return b;
    }


    /**
     * set中移除指定元素
     *
     * @param key
     * @param value
     * @return
     */
    public Long removeSet(String key, Object value) {
        Long size = null;
        try {
            size = redisTemplate.opsForZSet().remove(key, value);
        } catch (Exception e) {
            return size;
        }
        return size;
    }

    /**
     * set中移除指定元素
     *
     * @param key
     * @param value
     * @return
     */
    public Double incrementScore(String key, Object value, double delta) {
        Double size = null;
        try {
            size = redisTemplate.opsForZSet().incrementScore(key, value, delta);
        } catch (Exception e) {
            return size;
        }
        return size;
    }

    /**
     * 计算set集合大小
     *
     * @param key
     * @return
     */
    public Long countSet(String key) {
        Long size = null;
        try {
            size = redisTemplate.opsForZSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return size;
    }

    /**
     * 判断set中是否存在某元素
     *
     * @param key
     * @param min max
     * @return
     */
    public Long countSet(String key, double min, double max) {
        Long exist = 0L;
        try {
            exist = redisTemplate.opsForZSet().count(key, min, max);
        } catch (Exception e) {
            e.printStackTrace();

        }
        return exist;
    }

    /**
     * 判断set中是否存在某元素
     *
     * @param key
     * @param
     * @return
     */
    public Set range(String key) {
        Set exist = Collections.emptySet();
        try {
            exist = redisTemplate.opsForZSet().range(key, 0, 100000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return exist;
    }

    /**
     * 随机获取set中的一个元素
     *
     * @param key
     * @return
     */
    public Double score(String key, String value) {
        Double o = 0.0D;
        try {
            o = redisTemplate.opsForZSet().score(key, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return o;
    }


    /**
     * 按照Score值查询集合中的元素，结果从小到大排序
     *
     * @param key
     * @return
     */
    public Set reverseRangeByScore(String key, double min, double max) {
        Set set = Collections.emptySet();
        try {
            set = redisTemplate.opsForZSet().reverseRangeByScore(key, min, max);
            redisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, min, max);
            //返回值为:Set<ZSetOperations.TypedTuple<V>>
        } catch (Exception e) {
            e.printStackTrace();
        }
        return set;
    }

    /**
     * 遍历集合（和iterator一模一样）
     *
     * @param key
     * @return
     */
    public Set scan(String key) {
        Set set = Collections.emptySet();
        try {
            Cursor<ZSetOperations.TypedTuple<Object>> scan = redisTemplate.opsForZSet().scan(key, ScanOptions.NONE);
            while (scan.hasNext()) {
                ZSetOperations.TypedTuple<Object> item = scan.next();
                System.out.println(item.getValue() + ":" + item.getScore());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return set;
    }

}
